<?php 


	$prefix = __FLUXDIR . _DS . 'classes' . _DS . MySQL . _DS;

	require_once ($prefix.'select.fluxMySQL.class.php');
	require_once ($prefix.'common.fluxMySQL.class.php');
	require_once ($prefix.'insert.fluxMySQL.class.php');
	require_once ($prefix.'having.fluxMySQL.class.php');

	class fluxMySQL extends fluxDbCommon {

		private $config          = array();
		private $links           = array();
		private $currentDatabase = NULL;
		private $throwExceptions = TRUE; 
		private $fileDebugging   = FALSE;

		public function __construct ($array=NULL) {

				if (sizeof($array))  
					$this -> connect($array);
				else {
						  $msg = 'Invalid parameter specified for constructor of class ' . __CLASS__ . 
									 'array expected ' . gettype ($array) . ' given';
						  throw (new fluxXception ($msg));
				}

		}

		//loadConfigFromIniFile:
		//
		//Load configuration from ini file $iniFile and use the parameters given in $section
		//for connecting to the database

		public static function loadConfigFromIniFile ($iniFile=NULL,$section=NULL) {

			fluxFile::exists ($iniFile);
			$parameters =  parse_ini_file($iniFile,TRUE);

			//Check if the section given by the user exists in the ini file

			$sections = array_keys ($parameters);

			if (!in_array ($section,$sections)) {
				$msg = 'The section ->' . $section . 
						 '<- doesnt exists in the given ini file ' . $iniFile;

				throw (new fluxXception ($msg));

			}

			$con = new self ($parameters[$section]);

			return $con;

		}

		public function setFileDebugging ($boolean){
			return $this->fileDebugging=$boolean;
		}

		public function getFileDebugging (){
			return $this->fileDebugging;
		}

		public function setExceptions($boolean){
			return $this->throwExceptions=$boolean;
		}

		public function getExceptions (){
			return $this->throwExceptions;
		}

		public function setConfig ($array) {

			if (!sizeof ($array))
				throw (new Exception ('Invalid configuration array'));

			$keys       = array_keys ($array);
			$hasToBeIn  = array ('hostname'=>0,'username'=>0,'password'=>0,'port'=>0,'database'=>0);

			foreach ($hasToBeIn as $k => $v) {

					  if (!in_array ($k,$keys)) {
								 //Change for fluxXception add file writing error support to fluxXception
								 if ($this -> throwExceptions)
											throw (new fluxXception ($k . ' not found in initialization array'));
								 else
									die ();
						}

					  $this -> config[$k] = $array[$k];

			}


		}


		public function connect ($config=NULL) {
			
			$this -> setConfig ($config);

			extract ($this -> config);

			$hostname = (is_int($port)) ? $hostname.':'.$port : $hostname;

			$this->links[$database]  = @mysql_connect ($hostname,$username,$password);

			$this -> currentDatabase = $database;

			if (@mysql_error($this->links[$database])) {

				  $msg = 'Could not connect to database ' . $database .
							'please verify your connection data';

				  throw (new Exception ($msg));

			}

			@mysql_select_db ($database);

		}

		protected function writeWarning ($msg) {
				  $this->writeDebug($msg,'WARNING');
		}

		private function isConnectedToThisDatabase ($database=NULL) {

			  if (is_null ($database)) {
					 $database=$this->currentDatabase;
					 $this->writeWarning('uoo');
			  }

			  $msg = 'Youre not connected to ' . $database . ' Use $db -> connect first; Perhaps database ' .
				  'Engine is Down?';	

			  $this->isValidResource($this->links[$database],__METHOD__,$msg);

			  return TRUE;

		}

		public function getLink ($database=NULL){

				  if (is_null($database)){

							 $database=$this->currentDatabase;
							 $this->writeWarning('No database specified, using '.$database.' [its the current database]');
				  }

				  $this->isConnectedToThisDatabase ($database);

				  return ($this->links[$database]);

		}

		public function switchTo ($database) {

			  $this -> isConnectedToThisDatabase($database);
			  $this -> currentDatabase = $database;

		}

		public function filter($value=NULL){

			if (!$value)
				return;

			$l=$this->getLink();
			return mysql_real_escape_string ($value,$l);

		}

		public function doQuery ($query=NULL) {

			if (is_null($query))
				$this->throwError('No query was specified');

			$res = mysql_query ($query,$this->getLink());


			if ($err=mysql_error ($this->links[$this->currentDatabase])) {

				$error = '<h3>There was an error parsing your query</h3>' . "\n" .
							'<p style="color:#18AE18;">' . $query  . '</p>'  . "\n" .
							'<p style="color:#FF0000;">' . $err    . '</p>'  . "\n";

				$errorNoHtml = 'There was an error parsing your query' . "\n" . $query . $err;

				$this->writeDebug($errorNoHtml,'ERROR');
				$this->setFileDebugging(FALSE);
				$this->throwError($error);

			}

			return ($res);

		}

		public function rawQueryObject ($query,$filter=TRUE){

				  if ($filter)
				  	$query = mysql_real_escape_string ($query,$this->getLink());
				  return $this->parseQueryAsObject($this->doQuery($query));

		}

		public function rawQueryArray ($query=NULL,$filter=TRUE){

				  if ($filter)
						$query = mysql_real_escape_string ($query,$this->getLink());

				  return $this->parseQueryAsArray($this->doQuery($query));

		}

		public function rawQuery ($query,$filter=TRUE){
				  $query = ($filter) ? mysql_real_escape_string ($query,$this->getLink()) : $query;
				  return $this->doQuery($query);
		}

		public function throwError ($msg) {

			if ($this->fileDebugging){
				$exc = new Exception ($msg);
				$this->writeDebug($msg . "<- \n-> Stack Trace <- \n" . $exc->getTraceAsString(),'ERROR');
			}

			if (!$this->throwExceptions)
				die ();

			throw (new fluxXception ($msg));

		}

		private function writeDebug ($debug,$prepend) {

			$fp = @fopen ('/tmp/Errors-'.$this->currentDatabase.'.txt','a');
			@fwrite ($fp,"\n" . '['  . $prepend .']'. date ('[M/d/Y][H:i:s]') . ' -> '  . $debug . ' <- ' . "\n");
			@fclose ($fp);

		}

		public function isValidSqlMethod ($method) {

			switch ($method) {

				case 'select':
				case 'insert':
				case 'update':
				case 'drop'  :
				case 'create':
				case 'delete':
				case 'truncate':
				case 'show':
				case 'alter':
					return TRUE;
					break; //as a mere formality	

			}

			return FALSE;

		}


		public function selectAllFrom ($table=NULL,$orderBy=NULL,$ascDesc=NULL){

			$query = 'SELECT * FROM ' . $table;

			if(!is_null($orderBy))
				$query.=' ORDER BY ' . $orderBy;

			if (!is_null($ascDesc))
				$query.=' ' . $ascDesc;
					
			return $this->parseQueryAsObject($this->doQuery($query));

		}

		public function parseQueryAsObject ($resource) {

			$obj      = NULL;
			$objArray = array();

			while ($row = mysql_fetch_array ($resource,MYSQL_ASSOC)) {

				if($msg=mysql_error($this->links[$this->currentDatabase]))
					$this->throwError($msg);

				$obj = new stdClass();

				foreach  ($row as $k=>$v)
					$obj->$k=$v;

				$objArray[]=$obj;

				unset ($obj);

			}

			return $objArray;

		}

		private function isValidResource($resource,$method,$msg=NULL) {

			if (!is_resource ($resource)){
				if (is_null ($msg))
						  $this->throwError('Invalid resource specified for ' . $method);

			  $this->throwError('[->'.$method.'<-]'.$msg);

			}

			return TRUE;

		}

		protected function field_exists ($field,$fieldList) {
			
		}

		public function getFieldsFrom ($table=NULL) {
			$query = 'SHOW COLUMNS FROM ' . $table;
			return $this->parseQueryAsArray($this->doQuery($query));

		}

		public function parseQueryAsArray ($resource) {

			$this->isValidResource($resource,__METHOD__);

			$Array = array();

			while ($row = mysql_fetch_array ($resource,MYSQL_ASSOC)) {

				if($msg=mysql_error($this->links[$this->currentDatabase]))
					$this->throwError($msg);

				$Array[]=$row;

			}

			return ($Array);

		}

		public function setLink ($myLink=NULL,$database=NULL) {

				  $this->isValidResource($myLink,__METHOD__);
				  $this->setCurrentDatabase($database);
				  $this->links[$database]=$myLink;

		}

		public function setCurrentDatabase ($database=NULL){

				  if (is_null($database))
							 $this->throwError('Error setting current database to:[ ' . $database . ' ]');

				  $this->currentDatabase=$database;

		}

		public function getFieldsFromTable ($table) {

			$query = 'DESCRIBE ' . $table;
			$fields=$this->parseQueryAsArray($this->doQuery($query));
			return($fields);

		}



		public function showTables ($echo=NULL){

			$result = $this->parseQueryAsObject($this->doQuery('SHOW TABLES'));

			if(!$echo)
				return($result);

			while (list($k,$v) = each ($result)){
				  foreach(get_object_vars($v) as $key=>$value)
						echo $v->$key;								 	
			}
			

		}

		public function truncate ($table) {
				  $query = 'TRUNCATE ' . $table;
				  $this->doQuery($query);
				  return;
		}

		public function __call ($method,$args=NULL) {

			if (!$this->isValidSqlMethod($method))
				$this->throwError($method . ' is not a valid sql method');


			if ($method=='select' && !sizeof($args) || ($args[0]=='all' || $args[0]=='*'))
					  $args='*';

			$method ='flux'.ucwords($method);

			return (new $method($this->links [$this->currentDatabase],$method,$args,$this));

		}

	}



?>
